package com.gitee.wsl.ext.collection


public inline fun <T, K : Any, V : Any> Iterable<T>.associateNotNull(
    valueSelector: (T) -> Pair<K?, V?>?,
): Map<K, V> = mapNotNull {
    val (k, v) = valueSelector(it) ?: return@mapNotNull null
    if (k == null || v == null) return@mapNotNull null
    k to v
}.toMap()

public inline fun <T, K : Any> Iterable<T>.associateByNotNull(
    keySelector: (T) -> K?,
): Map<K, T> = mapNotNull {
    (keySelector(it) ?: return@mapNotNull null) to it
}.toMap()

//public inline fun <T, V : Any> Iterable<T>.associateWithNotNull(
//    valueSelector: (T) -> V?,
//): Map<T, V> = mapNotNull {
//    it to (valueSelector(it) ?: return@mapNotNull null)
//}.toMap()

fun <T, K, V> Iterable<T>.associateByNotNull(
    keySelector: (T) -> K?,
    valueTransform: (T) -> V?,
): Map<K, V> = buildMap {
    for (item in this@associateByNotNull) {
        val key = keySelector(item) ?: continue
        val value = valueTransform(item) ?: continue
        this[key] = value
    }
}



inline fun <T, K, V> Iterable<T>.associateNotNullTo(destination: MutableMap<K, V>, transform: (T) -> Pair<K, V>?): Map<K, V> {
    for (element in this) {
        val pair = transform(element)
        if (pair != null) {
            destination[pair.first] = pair.second
        }
    }

    return destination
}


inline fun <K, V, M : MutableMap<K, V>> Iterable<V>.associateByNotNullTo(destination: M, keySelector: (V) -> K?): M {
    for (element in this) {
        val key = keySelector(element)
        if (key != null) destination[key] = element
    }

    return destination
}

inline fun <K, V> Iterable<K>.associateWithNotNull(valueSelector: (K) -> V?): Map<K, V> {
    return associateWithNotNullTo(LinkedHashMap(), valueSelector)
}

inline fun <K, V, M : MutableMap<K, V>> Iterable<K>.associateWithNotNullTo(destination: M, valueSelector: (K) -> V?): M {
    for (element in this) {
        val value = valueSelector(element)
        if (value != null) destination[element] = value
    }

    return destination
}
